package com.NetSunWeiQin.chapter06;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.JarURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.Enumeration;
import java.util.Map;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.Manifest;

/**
 * 父类为URLConnection
 * 比较JarURLConnection和HttpURLConnection
 * 这个类通过JAR协议建立出了一个jar URL的连接
 * JarURLConnection的实例可以引用一个JAR的压缩包或者这种包里的某个文件.
 **/
public class JarURLConnectionDemo {

    private final static String FILE_URL = "D:\\java\\jarlib\\org\\apache\\httpcomponents\\httpcore\\4.4.13\\httpcore-4.4.13.jar";
    private final static String JAR_URL = "jar:file:/D:\\java\\jarlib\\org\\apache\\httpcomponents\\httpcore\\4.4.13\\httpcore-4.4.13.jar!/";
    private final static String DEFAULT_METHOD = "waitequalsnotifynotifyAlltoStringhashCodegetClass";  //这些默认方法不打印

    private static void getJarFileListName() {

        try {


            URL jarUrl = new URL(JAR_URL);

            // Create a jar URL getConnection object
            JarURLConnection jarURLConnection = (JarURLConnection) jarUrl.openConnection();

            // Get the jar file
            JarFile jarFile = jarURLConnection.getJarFile();

            // Get jar file name
            System.out.println("Jar Name: " + jarFile.getName());

            // When no entry is specified on the URL, the entry name is null
            System.out.println("\nJar Entry: " + jarURLConnection.getJarEntry());

            // Get the manifest of the jar
            Manifest manifest = jarFile.getManifest();

            // Print the manifest attributes
            System.out.println("\nManifest file attributes: ");
            for (Map.Entry entry : manifest.getMainAttributes().entrySet()) {
                System.out.println(entry.getKey() + ": " + entry.getValue());
            }



            // Get the main class name (the entry point class)
            String mainClassName = manifest.getMainAttributes().getValue(Attributes.Name.MAIN_CLASS);
            System.out.println(mainClassName);



            URL url = new File(FILE_URL).toURI().toURL();

            System.out.println("INFO FILE_URL == jarUrl?   "  + url .equals( jarUrl )   );
            URLClassLoader urlClassLoader = new URLClassLoader(new URL[]{url}, Thread.currentThread().getContextClassLoader());


            JarFile jar = new JarFile(FILE_URL);       //通过jarFile和JarEntry得到所有的类

            Enumeration<JarEntry> enumFiles = jar.entries();   //返回zip文件条目的枚举
            JarEntry entry;

            while (enumFiles.hasMoreElements()) {
                entry = enumFiles.nextElement();


                if (!entry.getName().contains("META-INF")) {
                    String classFullName = entry.getName();
                    if (!classFullName.endsWith(".class")) {
//                        classFullName = classFullName.substring(0, classFullName.length() - 1);
                        System.out.println("INFO   非class文件: " + classFullName);
                    } else {
                        String className = classFullName.substring(0, classFullName.length() - 6).replace("/", ".");   //去掉后缀.class
                        getClassInfo(className, urlClassLoader);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    private static void getClassInfo(String className, URLClassLoader urlClassLoader) throws ClassNotFoundException {

        Class<?> myclass = urlClassLoader.loadClass(className);

        System.out.println("*****************************");
        System.out.println("全类名:" + className);


        Method[] methods = myclass.getMethods();
        for (Method method : methods) {
            String methodName = method.getName();
            if (DEFAULT_METHOD.contains(methodName)) {
                continue;
            }
            System.out.println("方法名称:" + methodName);
            Class<?>[] parameterTypes = method.getParameterTypes();
            for (Class<?> clas : parameterTypes) {

                String parameterName = clas.getSimpleName();
                System.out.println("参数类型:" + parameterName);
            }
            System.out.println("==========================");
        }

    }






    /**
     *
     */
    public static void main(String[] args) throws Exception {

        getJarFileListName();
    }
}
